// glutTest1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "glut.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>  

#include <highgui.h>
#include "Calibration.h"
#include "ChessboardSurrogate.h"
#include "CreateCalibrationConfig.h"
#include "CalibrationResultTester.h"
#include "testSet.h"
#include "camModule.h"
#include "featureTests.h"
#include "find_obj.h"
#include "frameExtractor.h"
#include "Common.h"
#include "FrameKey.h"
#include "FeaturePlayer.h"
#include "SurfTracker.h"




//////////////////////////////////////////////////////////////////////////////////////////
testSet::testUnit* _currentTest;
//////////////////////////////////////////////////////////////////////////////////////////

#ifndef M_PI
#define M_PI 3.14159265358979323846264338327950288419716939937510
#endif

int MouseActive = FALSE;
float angleX = 0, angleY = 0;
int lastX, lastY;


void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
      case 27:
         exit(0);
         break;
   }
}

void processMouse(int button, int state, int x, int y) 
{
	if (state == GLUT_DOWN)
	{
		lastX = x;
		lastY = y;
	
		MouseActive = TRUE;			
	}
	else if (state == GLUT_UP)
	{
		MouseActive = FALSE;
	}
}

void processMouseActiveMotion(int x, int y) 
{
	if (MouseActive)
	{
		int dx = lastX - x;
		int dy = lastY - y;

		if (dx < 0)
			angleY+=2;
		else if (dx > 0)
			angleY-=2;


		if (dy < 0)
			angleX+=2;
		else if (dy > 0)
			angleX-=2;

		lastX = x;
		lastY = y;
	}

	glutPostRedisplay();
}

void init() 
{
	GLfloat front_color[] = {0,1,0,1};

   GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
   GLfloat mat_shininess[] = { 50.0 };

   GLfloat light_position[] = { 0.0, 0.0, -200.0, 1.0 };
   GLfloat light[] = { 1.0, 0.2, 0.2 };
   GLfloat lmodel_ambient[] = { 0.1, 0.1, 0.1, 1.0 };
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_SMOOTH);

   glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
   glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

   glLightfv(GL_LIGHT0, GL_POSITION, light_position);

   glLightfv(GL_LIGHT0, GL_DIFFUSE, light );
   glLightfv(GL_LIGHT0, GL_SPECULAR, light );
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);

   glEnable(GL_LIGHTING);
   glEnable(GL_LIGHT0);
   glEnable(GL_DEPTH_TEST);
}

void drawCoordinateSystem()
{
	glBegin(GL_LINES);
		glColor3f(1.0f,0.0f,0.0f); //y is red
		glVertex3i(0,200,0);
		glVertex3i(0,-5,0);
		glColor3f(0.0f,1.0f,0.0f); //x is green
		glVertex3i(200,0,0);
		glVertex3i(-5,0,0);
		glColor3f(0.0f,0.0f,1.0f); //z is blue
		glVertex3i(0,0,200);
		glVertex3i(0,0,-5);
	glEnd();
}

void calibrationTransform()
{
	glMultMatrixf(_currentTest->m);
}

void display()
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
  glPushMatrix();

	drawCoordinateSystem();
	
	ChessboardSurrogate s(6,8,50);
	s.Draw(20,20);

  glPopMatrix();
	
	// rotate word coorinate system
	glLoadIdentity();		

	gluLookAt(  0.0, 0.0, -testSet::znear*2,
			0.0, 0.0, 0.0,
			0.0, 1.0, 0.0);

	// accept 3d transformnation getted from calibration 
	// i expect to see surogate chessboard like photo chessboard
	//float translationData[] = {-1.83015060e+000, 1.80811465e+000, 1.44920006e+001};
	
	//glTranslatef(0,0, 200);
	
	calibrationTransform();

	glRotatef(angleX,1.0,0.0,0.0);
	glRotatef(angleY,0.0,1.0,0.0);
	

	//glMultMatrixf();
	//glScalef(4,4,4);

	glutSwapBuffers();
}

void reshape(int w, int h)
{
	glViewport(0, 0, w, h);       /* Establish viewing area to cover entire window. */
	glMatrixMode(GL_PROJECTION);  /* Start modifying the projection matrix. */
	glLoadIdentity();             /* Reset project matrix. */

	//gluPerspective(2.0, (GLfloat) w/(GLfloat) h, c_focal, c_focal + 1000.0);
	//int acpect = 40;
	//glFrustum((-c_cx)/acpect, (w - c_cx)/acpect, (-c_cy)/acpect, (h - c_cy)/acpect, c_focal, c_focal + 1000);	
	
	/*glFrustum( -znear*c_cx / c_focalX, znear*(w - c_cx) / c_focalX,
				-znear*c_cy / c_focalY, znear*(h - c_cy) / c_focalY, 
				znear, zfar);*/

	_currentTest->setupFrustum(w,h);

	glMatrixMode(GL_MODELVIEW);

	
	display();
}

int _tmain(int argc, char **argv)
{	
	//FeaturePlayer p("video\\1.avi");	
	//SurfTracker p("video\\1.avi");
	//p.StartPlay();
	
	//frameExtractor::extruct("video\\1.avi", "images");
	//featureTests::test1();
	find_obj::run("images\\5_left.png", "images\\5_right.png");
	return 0;

	cvNamedWindow("wnd");

	int imageCount = 8;
	char* file[8] = {
						"snapshots\\0.png",
						"snapshots\\1.png",
						"snapshots\\2.png",
						"snapshots\\3.png",
						"snapshots\\4.png",
						"snapshots\\5.png",
						"snapshots\\6.png",
						"snapshots\\7.png",
					};


	//	CreateCalibrationConfig::CreateFile(file, 8, "snapshots\\all.conf");
	//CalibrationResultTester::Test();
	//return 0;

	testSet::Init();
	_currentTest = testSet::tests[4];

	IplImage* img = cvLoadImage(_currentTest->filePath);
	cvFlip(img);
	cvFlip(img,img, 1);
	cvShowImage("wnd", img);
	
	//cvWaitKey(0);
	//cvReleaseImage(&img);
	//return 0;

  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutCreateWindow("test");  
  glutReshapeWindow(640, 480);
  
  init();
  
  glutDisplayFunc(display);
  glutReshapeFunc(reshape);

  glutMouseFunc(processMouse);
  glutMotionFunc(processMouseActiveMotion);
  glutKeyboardUpFunc(keyboard);
  
  glutMainLoop();
  return 0;             /* ANSI C requires main to return int. */
}
